package io.gitee.guoguoleo.chain;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import io.gitee.guoguoleo.utils.JdbcUtil;
import io.gitee.guoguoleo.utils.SqlRenderUtil;
import io.gitee.guoguoleo.utils.TableUtil;
import io.gitee.guoguoleo.wrapper.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.SelectItem;
import org.springframework.jdbc.core.JdbcTemplate;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;

@Slf4j
public class QueryChain<T> extends Chain<T> {
    private final PlainSelect plainSelect;


    public QueryChain(Class<T> clazz, JdbcTemplate jdbcTemplate) {
        super(clazz, jdbcTemplate);

        //初始化select
        this.plainSelect = new PlainSelect();
        String tableName = TableUtil.getTableName(clazz);
        Table table = new Table(tableName);
        this.plainSelect.setFromItem(table);


    }


    /**
     * 查询一个
     *
     * @param sql sql
     * @return 泛型对象
     */
    public T get(String sql) {
        return JdbcUtil.get(this.clazz, this.jdbcTemplate, sql);
    }

    /**
     * 自定义sql，查询列表
     *
     * @param sql sql语句
     * @return 泛型对象列表
     */
    public List<T> list(String sql) {
        return JdbcUtil.list(this.clazz, this.jdbcTemplate, sql);
    }


    public T getById(Serializable id) {
        this.eq(this.fieldList.getIdField().getFieldName(), id);
        return this.one();
    }


    public List<T> listByIds(Collection<? extends Serializable> ids) {
        if (CollUtil.isEmpty(ids)) {
            throw new RuntimeException("id列表不能为空");
        }
        this.in(this.fieldList.getIdField().getFieldName(), ids);
        return this.list();
    }

    public List<T> listByIds(Serializable... ids) {
        return this.listByIds(ListUtil.toList(ids));
    }


    @Override
    public T one() {
        this.renderSelect();
        return this.get(this.plainSelect.toString());
    }

    @Override
    public T one(QueryWrapper<T> queryWrapper) {
        this.whereExpressionList = queryWrapper.getWhere();
        this.orderByElementList = queryWrapper.getOrderBy();
        this.selectColumnList = queryWrapper.getSelect();
        this.excludeSelectColumnList = queryWrapper.getExclude();
        this.renderSelect();
        return this.get(this.plainSelect.toString());
    }

    @Override
    public List<T> list() {
        this.renderSelect();
        return this.list(this.plainSelect.toString());
    }

    @Override
    public List<T> list(QueryWrapper<T> queryWrapper) {
        this.whereExpressionList = queryWrapper.getWhere();
        this.orderByElementList = queryWrapper.getOrderBy();
        this.selectColumnList = queryWrapper.getSelect();
        this.excludeSelectColumnList = queryWrapper.getExclude();
        this.renderSelect();
        return this.list(this.plainSelect.toString());
    }

    /**
     * 渲染select
     */
    private void renderSelect() {
        List<SelectItem<?>> selectItemList = SqlRenderUtil.renderSelectItem(this.fieldList, this.selectColumnList, this.excludeSelectColumnList);
        this.plainSelect.setSelectItems(selectItemList);
        this.plainSelect.setWhere(SqlRenderUtil.renderCommonWhere(this.fieldList.getDelField()));
        if (CollUtil.isNotEmpty(this.whereExpressionList)) {
            this.plainSelect.setWhere(SqlRenderUtil.renderWhere(this.plainSelect.getWhere(), this.whereExpressionList));
        }
        if (CollUtil.isNotEmpty(this.orderByElementList)) {
            this.plainSelect.setOrderByElements(this.orderByElementList);
        }
    }


}
